package com.ybear.mvp;

import static com.ybear.mvp.event.MvpEventObserver.EventType.DISPATCH_GENERIC_MOTION;
import static com.ybear.mvp.event.MvpEventObserver.EventType.DISPATCH_KEY;
import static com.ybear.mvp.event.MvpEventObserver.EventType.DISPATCH_KEY_SHORTCUT;
import static com.ybear.mvp.event.MvpEventObserver.EventType.DISPATCH_TOUCH;
import static com.ybear.mvp.event.MvpEventObserver.EventType.DISPATCH_TRACKBALL;
import static com.ybear.mvp.event.MvpEventObserver.EventType.ON_TOUCH;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.os.PersistableBundle;
import android.util.SparseArray;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.ybear.mvp.annotations.LifeStatus;
import com.ybear.mvp.annotations.LifeTrigger;
import com.ybear.mvp.event.MvpEventObserver;
import com.ybear.mvp.event.OnEventCallback;
import com.ybear.mvp.handler.DelegateHandler;
import com.ybear.mvp.handler.Handler;
import com.ybear.mvp.handler.HandlerCallback;
import com.ybear.mvp.model.MvpModel;
import com.ybear.mvp.view.MvpActivity;
import com.ybear.mvp.view.MvpAppCompatActivity;
import com.ybear.mvp.view.MvpFragmentActivity;
import com.ybear.mvp.view.fragment.MvpAppCompatDialogFragment;
import com.ybear.mvp.view.fragment.MvpDialogFragment;
import com.ybear.mvp.view.fragment.MvpFragment;

import java.lang.ref.WeakReference;
import java.util.List;

/**
 * V层生命周期处理
 * @param <VP>
 */
public final class ViewLife<VP extends BaseVP> extends MvpModel {
    private final SparseArray<OnViewLifeListener> mListener = new SparseArray<>();
//    private OnEventCallback mOnEventCallback;
    @LifeStatus
    private int mLifeStatus;    //当前生命周期状态
    @LifeTrigger
    private int mLifeTrigger;   //触发器

    public int getLifeStatus() { return mLifeStatus; }

    public int getTriggerStatus() { return mLifeTrigger; }

    public void onTriggerStatus(int trigger) { mLifeTrigger = trigger; }

    public void onNewIntent(@NonNull VP t, Intent intent) {
        Bundle b = newBundle();
        b.putParcelable( LifeTrigger.KEY_INTENT, intent );
        onLifeStatus( t, LifeStatus.NEW_INTENT, b );
    }

    public void onAttach(@NonNull VP t) { onLifeStatus( t, LifeStatus.ATTACH, null ); }

    public void onCreate(@NonNull VP t, @Nullable Bundle savedInstanceState) {
        onLifeStatus( t, LifeStatus.CREATE, savedInstanceState );
    }

    public void onCreateView(@NonNull VP t, @Nullable Bundle savedInstanceState) {
        onLifeStatus( t, LifeStatus.CREATE_VIEW, savedInstanceState );
    }

    public void onActivityCreate(@NonNull VP t, @Nullable Bundle savedInstanceState) {
        onLifeStatus( t, LifeStatus.ACTIVITY_CREATED, savedInstanceState );
    }

    public void onStart(@NonNull VP t) { onLifeStatus( t, LifeStatus.START, null ); }

    public void onReStart(@NonNull VP t) { onLifeStatus( t, LifeStatus.RESTART, null ); }

    public void onResume(@NonNull VP t) { onLifeStatus( t, LifeStatus.RESUME, null ); }

    public void onPause(@NonNull VP t) { onLifeStatus( t, LifeStatus.PAUSE, null ); }

    public void onStop(@NonNull VP t) { onLifeStatus( t, LifeStatus.STOP, null ); }

    public void onDestroyView(@NonNull VP t) { onLifeStatus( t, LifeStatus.DESTROY_VIEW, null ); }

    public void onDestroy(@NonNull VP t) { onLifeStatus( t, LifeStatus.DESTROY, null ); }

    public void onDetach(@NonNull VP t) { onLifeStatus( t, LifeStatus.DETACH, null ); }

    /**
     * 处理请求权限结果
     * @param t                 this
     * @param requestCode       请求码
     * @param permissions       权限
     * @param grantResults      结果
     */
    public void onRequestPermissionsResult(@NonNull VP t, int requestCode,
                                                     @NonNull String[] permissions,
                                                     @NonNull int[] grantResults) {
        Bundle b = newBundle();
        b.putInt( LifeTrigger.KEY_REQUEST_CODE, requestCode );
        b.putStringArray( LifeTrigger.KEY_PERMISSIONS, permissions );
        b.putIntArray( LifeTrigger.KEY_GRANT_RESULTS, grantResults );
        onLifeTrigger( t, LifeTrigger.REQUEST_PERMISSIONS_RESULT, b );
    }

    /**
     * 处理页面请求结果
     * @param t                 this
     * @param requestCode       请求码
     * @param resultCode        结果码
     * @param intent            数据
     */
    public void onActivityResult(@NonNull VP t, int requestCode,
                                           int resultCode, @Nullable Intent intent) {
        Bundle b = newBundle();
        b.putInt( LifeTrigger.KEY_REQUEST_CODE, requestCode );
        b.putInt( LifeTrigger.KEY_RESULT_CODE, resultCode );
        b.putParcelable( LifeTrigger.KEY_INTENT, intent );
        onLifeTrigger( t, LifeTrigger.ACTIVITY_RESULT, b );
    }

    /**
     * 处理保存状态
     * @param t             this
     * @param outState      保存数据
     */
    public void onSaveInstanceState(@NonNull VP t, @NonNull Bundle outState) {
        Bundle b = newBundle();
        b.putParcelable( LifeTrigger.KEY_BUNDLE, outState );
        onLifeTrigger( t, LifeTrigger.SAVE_INSTANCE_STATE, b );
    }

    /**
     * 处理保存状态
     * @param t                     this
     * @param outState              保存数据
     * @param outPersistentState    持久化状态
     */
    public void onSaveInstanceState(@NonNull VP t, @NonNull Bundle outState,
                                        @NonNull PersistableBundle outPersistentState) {
        Bundle b = newBundle();
        b.putParcelable( LifeTrigger.KEY_BUNDLE, outState );
        b.putParcelable( LifeTrigger.KEY_PERSISTABLE_BUNDLE,
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? outPersistentState : null );
        onLifeTrigger( t, LifeTrigger.SAVE_INSTANCE_STATE_2, b );
    }

    /**
     * Fragment隐藏发生改变
     * @param t             this
     * @param hidden        是否隐藏
     */
    public void onHiddenChanged(@NonNull VP t, boolean hidden) {
        Bundle b = newBundle();
        b.clear();
        b.putBoolean( LifeTrigger.KEY_HIDDEN, hidden );
        onLifeTrigger( t, LifeTrigger.HIDDEN_CHANGED, b );
    }

    /**
     * 处理Touch事件
     * @param t             this
     * @param ret           调度事件的返回值
     * @param ev            调度事件
     * @param <T>           事件泛型
     * @return              调度事件的返回值
     */
    public <T extends InputEvent> boolean onTouchEvent(@NonNull VP t,
                                                       boolean ret,
                                                       @NonNull T ev) {
        MvpEventObserver.get().onDispatch( t.getActivity(), ON_TOUCH, ev );
        return ret;
    }

    /**
     * 调度Touch事件
     * @param t             this
     * @param ret           调度事件的返回值
     * @param ev            调度事件
     * @param <T>           事件泛型
     * @return              调度事件的返回值
     */
    public <T extends InputEvent> boolean dispatchTouchEvent(@NonNull VP t,
                                                             boolean ret,
                                                             @NonNull T ev) {
        MvpEventObserver.get().onDispatch( t.getActivity(), DISPATCH_TOUCH, ev );
        return ret;
    }

    /**
     * 调度Key事件
     * @param t             this
     * @param ret           调度事件的返回值
     * @param ev            调度事件
     * @param <T>           事件泛型
     * @return              调度事件的返回值
     */
    public <T extends InputEvent> boolean dispatchKeyEvent(@NonNull VP t,
                                                           boolean ret,
                                                           @NonNull T ev) {
        MvpEventObserver.get().onDispatch( t.getActivity(), DISPATCH_KEY, ev );
        return ret;
    }

    public <T extends InputEvent> boolean dispatchKeyShortcutEvent(@NonNull VP t,
                                                                   boolean ret,
                                                                   @NonNull T ev) {
        MvpEventObserver.get().onDispatch( t.getActivity(), DISPATCH_KEY_SHORTCUT, ev );
        return ret;
    }

    public <T extends InputEvent> boolean dispatchTrackballEvent(@NonNull VP t,
                                                                 boolean ret,
                                                                 @NonNull T ev) {
        MvpEventObserver.get().onDispatch( t.getActivity(), DISPATCH_TRACKBALL, ev );
        return ret;
    }

    public <T extends InputEvent> boolean dispatchGenericMotionEvent(@NonNull VP t,
                                                                     boolean ret,
                                                                     @NonNull T ev) {
        MvpEventObserver.get().onDispatch( t.getActivity(), DISPATCH_GENERIC_MOTION, ev );
        return ret;
    }

    /**
     * 虚引用Application上下文
     * @param activity  传入的泛型为Activity
     * @param <A>       泛型继承 {@link Activity}
     * @return          返回上下文
     */
    @Nullable
    public <A extends Activity> Context getApplicationContext(@Nullable A activity) {
        return activity != null ? activity.getApplicationContext() : null;
    }


    /**
     * 虚引用上下文
     * @param activity  传入的泛型为Activity
     * @param <A>       泛型继承 {@link Activity}
     * @return          返回上下文
     */
    @Nullable
    public <A extends Activity> Context getContext(@NonNull A activity) {
        return getActivity( activity );
    }

    /**
     * 获取传入的Activity，由于this在匿名内部类中可能无法使用，通过在activity中调用此方法直接获取。
     * @param activity  this
     * @param <A>       this必须继承Activity
     * @return          this
     */
    @Nullable
    public <A extends Activity> Activity getActivity(@NonNull A activity) {
        return new WeakReference<>( activity ).get();
    }

    /**
     * 查找View
     * @param fragment  this
     * @param id        资源id
     * @param <T>       返回的View
     * @return          View
     */
    @Nullable
    public <T extends View> T findViewById(MvpFragment<?> fragment, @IdRes int id) {
        if( fragment == null ) return null;
        View v = fragment.getView();
        return v != null ? v.findViewById( id ) : null;
    }

    /**
     * 查找View
     * @param fragment  this
     * @param id        资源id
     * @param <T>       返回的View
     * @return          View
     */
    @Nullable
    public <T extends View> T findViewById(com.ybear.mvp.view.MvpFragment<?> fragment, @IdRes int id) {
        if( fragment == null ) return null;
        View v = fragment.getView();
        return v != null ? v.findViewById( id ) : null;
    }

    /**
     * 查找View
     * @param fragment  this
     * @param id        资源id
     * @param <T>       返回的View
     * @return          View
     */
    @Nullable
    public <T extends View> T findViewById(MvpDialogFragment<?> fragment, @IdRes int id) {
        if( fragment == null ) return null;
        View v = fragment.getView();
        return v != null ? v.findViewById( id ) : null;
    }

    /**
     * 查找View
     * @param fragment  this
     * @param id        资源id
     * @param <T>       返回的View
     * @return          View
     */
    @Nullable
    public <T extends View> T findViewById(com.ybear.mvp.view.MvpDialogFragment<?> fragment, @IdRes int id) {
        if( fragment == null ) return null;
        View v = fragment.getView();
        return v != null ? v.findViewById( id ) : null;
    }

    /**
     * 查找View
     * @param fragment  this
     * @param id        资源id
     * @param <T>       返回的View
     * @return          View
     */
    @Nullable
    public <T extends View> T findViewById(MvpAppCompatDialogFragment<?> fragment, @IdRes int id) {
        if( fragment == null ) return null;
        View v = fragment.getView();
        return v != null ? v.findViewById( id ) : null;
    }

    /**
     * 结束页面
     * @param t     this
     */
    public void finishOfFragment(@NonNull VP t) {
        Activity a = t.getActivity();
        if( a != null ) a.finish();
    }

    /**
     * 获取Handler
     * @param activity  {@link Fragment#getActivity()}
     *                  {@link android.app.Fragment#getActivity()}
     * @return          Handler
     */
    @NonNull
    public Handler getHandlerOfFragment(@Nullable Activity activity, @Nullable HandlerCallback callback) {
        if( activity instanceof MvpActivity) {
            return ((MvpActivity<?>) activity).getHandler();
        }
        if( activity instanceof MvpAppCompatActivity) {
            return ((MvpAppCompatActivity<?>) activity).getHandler();
        }
        if( activity instanceof MvpFragmentActivity) {
            return ((MvpFragmentActivity<?>) activity).getHandler();
        }
        return DelegateHandler.create( callback );
//        //Fragment的Activity没有继承上述类
//        throw new IllegalStateException("The fragment of Activity not extends the Mvp**Activity.");
    }

    public void handleMessageToFragments(@NonNull Activity activity, @NonNull Message msg) {
        if( activity instanceof MvpActivity ) {
            if ( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ) {
                List<android.app.Fragment> fragments = activity.getFragmentManager().getFragments();
                if( fragments == null ) return;
                for( android.app.Fragment f : fragments ) {
                    if( f instanceof HandlerCallback ) {
                        ((HandlerCallback) f).handleMessage( msg );
                    }
                }
            }
        }else {
            List<Fragment> fragments = null;
            if( activity instanceof MvpAppCompatActivity ) {
                fragments = ((MvpAppCompatActivity<?>) activity).getSupportFragmentManager().getFragments();
            }else if( activity instanceof MvpFragmentActivity ) {
                fragments = ((MvpFragmentActivity<?>) activity).getSupportFragmentManager().getFragments();
            }
            if( fragments == null ) return;
            for( Fragment f : fragments ) {
                if( f instanceof HandlerCallback ) {
                    ((HandlerCallback) f).handleMessage( msg );
                }
            }
        }
    }

    public void dispatchMessageToFragments(@NonNull Activity activity, @NonNull Message msg) {
        if( activity instanceof MvpActivity ) {
            if ( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ) {
                List<android.app.Fragment> fragments = activity.getFragmentManager().getFragments();
                if( fragments == null ) return;
                for( android.app.Fragment f : fragments ) {
                    if( f instanceof HandlerCallback ) {
                        ((HandlerCallback) f).dispatchMessage( msg );
                    }
                }
            }
        }else {
            List<Fragment> fragments = null;
            if( activity instanceof MvpAppCompatActivity ) {
                fragments = ((MvpAppCompatActivity<?>) activity).getSupportFragmentManager().getFragments();
            }else if( activity instanceof MvpFragmentActivity ) {
                fragments = ((MvpFragmentActivity<?>) activity).getSupportFragmentManager().getFragments();
            }
            if( fragments == null ) return;
            for( Fragment f : fragments ) {
                if( f instanceof HandlerCallback ) {
                    ((HandlerCallback) f).dispatchMessage( msg );
                }
            }
        }
    }

    /**
     * 注册P层
     * @param t         this
     * @param l         V层的生命周期监听器
     */
    public void registerPresenter(@NonNull VP t, @Nullable OnViewLifeListener l) {
        mListener.put( t.hashCode(), l );
    }

    /**
     * 解除P层
     * @param t         this
     */
    public void unRegisterPresenter(@NonNull VP t) { mListener.remove( t.hashCode() ); }

    /**
     * Fragment传递参数给FragmentActivity
     * @param t         this
     * @param args      参数
     */
    public void setArgumentsToActivity(@Nullable VP t, @Nullable Bundle args) {
        if( t == null ) return;
        Activity activity = t.getActivity();
        
        if( activity instanceof MvpAppCompatActivity ) {
            ((MvpAppCompatActivity)activity).onCallArguments( args );
        } 
        else if( activity instanceof MvpFragmentActivity ) {
            ((MvpFragmentActivity)activity).onCallArguments( args );
        }
        else if( activity instanceof MvpActivity ) {
            ((MvpActivity)activity).onCallArguments( args );
        }

//        //获取P层的生命周期接口
//        OnViewLifeListener l = getOnViewLifeListenerOfPresenter( t );
//        if( l != null ) l.onCallArguments( args );
    }

//    /**
//     * FragmentActivity传递参数给Fragment
//     * @param fragment  传递的Fragment
//     * @param args      参数
//     */
//    public void setArgumentsToFragment(MvpFragment fragment, @Nullable Bundle args) {
//        if( fragment == null ) return;
//        fragment.setArguments( args );
//        fragment.onCallArguments( args );
//    }
//
//    /**
//     * FragmentActivity传递参数给Fragment
//     * @param fragment  传递的Fragment
//     * @param args      参数
//     */
//    public void setArgumentsToFragment(com.ybear.mvp.demo.view.MvpFragment fragment,
//                                          @Nullable Bundle args) {
//        if( fragment == null ) return;
//        fragment.setArguments( args );
//        fragment.onCallArguments( args );
//    }

    public Bundle newBundle() { return new Bundle(); }

    /**
     * 处理生命周期
     * @param t         this
     * @param status    this当前的生命周期
     * @param b         需要处理的数据。不需要为null
     */
    private void onLifeStatus(@Nullable VP t, @LifeStatus int status, @Nullable Bundle b) {
        mLifeStatus = status;
        if( t == null ) return;
        //获取P层的生命周期接口
        OnViewLifeListener l = getOnViewLifeListenerOfPresenter( t );
        if( l == null ) return;
        l.onLifeStatus( status, b );
        switch ( status ) {
            case LifeStatus.NEW_INTENT:
                l.onLifeNewIntent( b == null ? null : b.getParcelable( LifeTrigger.KEY_INTENT ) );
                break;
            case LifeStatus.ATTACH:                             //Fragment
                l.onLifeAttach();
                break;
            case LifeStatus.CREATE:                             //Activity、Fragment
                //注册事件监听
                registerEvent( t );
                l.onLifeCreate( b );
                break;
            case LifeStatus.CREATE_VIEW:                        //Fragment
                l.onLifeCreateView( b );
                break;
            case LifeStatus.ACTIVITY_CREATED:                   //Fragment
                l.onLifeActivityCreate( b );
                break;
            case LifeStatus.START:                              //Activity、Fragment
                l.onLifeStart();
                break;
            case LifeStatus.RESTART:                            //Activity、Fragment
                l.onLifeReStart();
                break;
            case LifeStatus.RESUME:                             //Activity、Fragment
                l.onLifeResume();
                break;
            case LifeStatus.PAUSE:                              //Activity、Fragment
                l.onLifePause();
                break;
            case LifeStatus.STOP:                               //Activity、Fragment
                l.onLifeStop();
                break;
            case LifeStatus.DESTROY_VIEW:                       //Fragment
                l.onLifeDestroyView();
                break;
            case LifeStatus.DESTROY:                            //Activity、Fragment
                l.onLifeDestroy();
                //解除事件监听
                unRegisterEvent( t );
                break;
            case LifeStatus.DETACH:                             //Fragment
                l.onLifeDetach();
                break;
        }
    }

    /**
     * 注册事件监听器
     * @param t         this
     */
    private void registerEvent(@NonNull VP t) {
        Activity activity = t.getActivity();
        if( activity == null ) return;
//        if( mOnEventCallback != null ) return;
        OnEventCallback onEventCallback = new OnEventCallback() {
            //获取P层的生命周期接口
            OnViewLifeListener l = getOnViewLifeListenerOfPresenter( t );
            @Override
            public void onTouchEvent(MotionEvent ev) {
                if( l != null ) l.onTouchEvent( ev );
            }
            @Override
            public void dispatchTouchEvent(MotionEvent ev) {
                if( l != null ) l.dispatchTouchEvent( ev );
            }
            @Override
            public void dispatchKeyEvent(KeyEvent ev) {
                if( l != null ) l.dispatchKeyEvent( ev );
            }

            @Override
            public void dispatchKeyShortcutEvent(KeyEvent ev) {
                if( l != null ) l.dispatchKeyShortcutEvent( ev );
            }

            @Override
            public void dispatchTrackballEvent(MotionEvent ev) {
                if( l != null ) l.dispatchTrackballEvent( ev );
            }

            @Override
            public void dispatchGenericMotionEvent(MotionEvent ev) {
                if( l != null ) l.dispatchGenericMotionEvent( ev );
            }
        };
        MvpEventObserver.get().registerEvent( activity, onEventCallback );
    }

    /**
     * 解除事件监听器
     */
    private void unRegisterEvent(@NonNull VP t) {
        MvpEventObserver.get().unRegisterEvent( t.getActivity() );
//        mOnEventCallback = null;
    }

    /**
     * V层生命周期的触发器
     * @param t         this
     * @param trigger   触发内容
     * @param b         数据
     */
    private void onLifeTrigger(VP t, @LifeTrigger int trigger, @Nullable Bundle b) {
        //获取P层的生命周期接口
        OnViewLifeListener l = getOnViewLifeListenerOfPresenter( t );
        int requestCode;
        Bundle state;
        if( l == null ) return;
        l.onTriggerStatus( trigger, b );
        switch ( trigger ) {
            case LifeTrigger.REQUEST_PERMISSIONS_RESULT:    //请求权限的结果
                //请求的权限码
                requestCode = b != null ? b.getInt( LifeTrigger.KEY_REQUEST_CODE ) : 0;
                //请求的权限
                String[] permissions = b != null &&
                        (permissions = b.getStringArray( LifeTrigger.KEY_PERMISSIONS )) != null ?
                        permissions : new String[0];
                //请求结果
                int[] grantResults = b != null &&
                        (grantResults = b.getIntArray( LifeTrigger.KEY_GRANT_RESULTS )) != null ?
                        grantResults : new int[0];
                //回调处理权限结果
                l.onTriggerRequestPermissionsResult( requestCode, permissions, grantResults );
                break;
            case LifeTrigger.ACTIVITY_RESULT:               //页面请求的结果
                //页面请求码
                requestCode = b != null ? b.getInt( LifeTrigger.KEY_REQUEST_CODE ) : 0;
                //回调的结果码
                int resultCode = b != null ? b.getInt( LifeTrigger.KEY_RESULT_CODE ) : 0;
                //数据
                Intent data = b != null &&
                        (data = b.getParcelable( LifeTrigger.KEY_INTENT )) != null ?
                        data : null;
                //回调页面请求结果
                l.onTriggerActivityResult( requestCode, resultCode, data );
                break;
            case LifeTrigger.SAVE_INSTANCE_STATE:           //页面保存状态
                state = b != null && (state = b.getParcelable( LifeTrigger.KEY_BUNDLE )) != null ?
                        state : newBundle();
                l.onTriggerSaveInstanceState( state );
                break;
            case LifeTrigger.SAVE_INSTANCE_STATE_2:         //页面保存状态（2个参数）
                state = b != null && (state = b.getParcelable( LifeTrigger.KEY_BUNDLE )) != null ?
                        state : newBundle();
                PersistableBundle pb = b != null &&
                        (pb = b.getParcelable( LifeTrigger.KEY_PERSISTABLE_BUNDLE )) != null ?
                        pb : null;
                l.onTriggerSaveInstanceState( state, pb );
                break;
            case LifeTrigger.HIDDEN_CHANGED:                //Fragment隐藏发生改变
                l.onTriggerHiddenChanged( b != null && b.getBoolean( LifeTrigger.KEY_HIDDEN ) );
                break;
        }
    }

    /**
     * 获取P层的生命周期接口
     * @param t     this
     * @return      生命周期接口
     */
    @Nullable
    private OnViewLifeListener getOnViewLifeListenerOfPresenter(VP t) {
        return mListener.get( t.hashCode() );
    }
}